﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace GT.UI.WinForms
{

    public class SubclassedWindow : NativeWindow
    {
        public delegate void WindowProcHandler(ref Message m, ref bool Handled);
        public event WindowProcHandler WindowProc;

        protected override void WndProc(ref Message m)
        {
            bool handled = false;
            if (WindowProc != null)
                WindowProc(ref m, ref handled);
            
            if (!handled)
                base.WndProc(ref m);
        }
    }

    public static class UI
    {
        public static ProgressDialog CreateStatusDialog(params string[] dialogOptions)
        {
            var opts = new DialogCreationOptions();
            dialogOptions.ForEach(i =>
                {
                    opts |= (new DialogCreationOptions()).GetEnumValue(i, false);
                });

            return CreateStatusDialog(opts);
        }

        public static ProgressDialog CreateStatusDialog(params DialogCreationOptions[] dialogOptions)
        {
            
            var opts = new DialogCreationOptions();
            var values = new ProgressDialogCreationValues();
            dialogOptions.ForEach(i => opts |= i);
            values.Options = opts;
            return CreateStatusDialog(values);
            
        }

        //public static ProgressDialog CreateStatusDialog(object dialogValues)
        //{
        //    var setupVals = new ProgressDialogCreationValues();
        //}

        public static ProgressDialog CreateStatusDialog(ProgressDialogCreationValues dialogValues)
        {
            var ret = new ProgressDialog();
            var opts = dialogValues.Options;
            ret.HostForm.TopMost = opts.HasFlag(DialogCreationOptions.AlwaysOnTop);
            ret.HostForm.FormBorderStyle = (opts.HasFlag(DialogCreationOptions.Resizable) ? FormBorderStyle.Sizable : FormBorderStyle.Fixed3D);
            ret.AllowDrag = (opts.HasFlag(DialogCreationOptions.Draggable));
            ret.OpenModal = (opts.HasFlag(DialogCreationOptions.Modal));
            ret.HostForm.Visible = (opts.HasFlag(DialogCreationOptions.AutoOpen));
            return ret;
        }

        public static string GetOpenFileName(string title = "Open File", string filter = "All files|*")
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = filter;
            dlg.Title = title;
            if (dlg.ShowDialog() == DialogResult.OK)
                return dlg.FileName;
            return string.Empty;
        }

        public static string[] GetOpenFileNames(string title = "Open Files", string filter = "All files|*")
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = filter;
            dlg.Title = title;
            dlg.Multiselect = true;
            if (dlg.ShowDialog() == DialogResult.OK)
                return dlg.FileNames;
            return new string[] { };
        }

        public static string GetSaveFileName(string title = "Save File", string filter = "All files|*")
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = filter;
            dlg.Title = title;
            if (dlg.ShowDialog() == DialogResult.OK)
                return dlg.FileName;
            return string.Empty;
        }

        public static Color GetColor(Color[] customColors = null)
        {
            ColorDialog dlg = new ColorDialog();
            dlg.AllowFullOpen = true;
            dlg.AnyColor = true;
            dlg.SolidColorOnly = false;
            if (customColors != null)
                dlg.CustomColors = customColors.Select(c => (int)c.ToArgb()).ToArray();
            
            if (dlg.ShowDialog() == DialogResult.OK)
                return dlg.Color;
            return Color.Empty;
        }

        public static DialogResult GetStringInput(ref string value, string title = "Input", string promptText = "Value:")
        {
            Form form = new Form();
            Label label = new Label();
            TextBox textBox = new TextBox();
            Button buttonOk = new Button();
            Button buttonCancel = new Button();

            form.Text = title;
            label.Text = promptText;
            textBox.Text = value;

            buttonOk.Text = "OK";
            buttonCancel.Text = "Cancel";
            buttonOk.DialogResult = DialogResult.OK;
            buttonCancel.DialogResult = DialogResult.Cancel;

            label.SetBounds(9, 20, 372, 13);
            textBox.SetBounds(12, 36, 372, 20);
            buttonOk.SetBounds(228, 72, 75, 23);
            buttonCancel.SetBounds(309, 72, 75, 23);

            label.AutoSize = true;
            textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
            buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;

            form.ClientSize = new Size(396, 107);
            form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
            form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
            form.FormBorderStyle = FormBorderStyle.FixedDialog;
            form.StartPosition = FormStartPosition.CenterScreen;
            form.MinimizeBox = false;
            form.MaximizeBox = false;
            form.AcceptButton = buttonOk;
            form.CancelButton = buttonCancel;

            textBox.SelectAll();

            DialogResult dialogResult = form.ShowDialog();
            value = textBox.Text;
            return dialogResult;
        }
    }

    public class ProgressDialogCreationValues
    {
        public string Text { get; set; }
        public string Title { get; set; }
        public int Value { get; set; }
        public ProgressBarStyle Style { get; set; }
        public int MinValue { get; set; }
        public int MaxValue { get; set; }
        public EventHandler Completed { get; set; }
        public FormClosedEventHandler Closed { get; set; }
        public DialogCreationOptions Options { get; set; }

        public ProgressDialogCreationValues()
        {
            Title = "Status";
            Text = string.Empty;
            Value = 0;
            MinValue = 0;
            MaxValue = 0;
            Completed = (src, ev) => { };
            Closed = (src, ev) => { };
        }
    }

    public class DialogButton
    {
        private Button _button;

        public DialogButton()
        {
            _button = new Button()
            {
                ImageAlign = ContentAlignment.MiddleLeft
            };

            _button.Text = "Button";
        }

        public DialogButton(DialogButtonValues creationValues)
            : this()
        {
            Enabled = creationValues.Enabled;
            Text = creationValues.Text;
            Icon = creationValues.Icon;
            Click(creationValues.Click);
        }

        public DialogButton(object creationValues)
            : this()
        {
            Enabled = creationValues.GetPropertyValue<bool>("Enabled", false);
            Text = creationValues.GetPropertyValue<string>("Text", false);
            Icon = creationValues.GetPropertyValue<Image>("Icon", false);
            Click(creationValues.GetPropertyValue<EventHandler>("Click", false));
        }

        public DialogButton(params string[] buttonOptions)
            : this()
        {
            var comparer = new Comparer<string>((x, y) => x.ToLower().Equals(y.ToLower()));
            Enabled = buttonOptions.Contains("enabled", comparer);
        }

        private DialogButton(Button baseButton)
        {
            _button = baseButton;
        }

        public string Text
        {
            get { return _button.Text; }
            set { _button.Text = value; }
        }

        public bool Enabled
        {
            get { return _button.Enabled; }
            set { _button.Enabled = value; }
        }

        public Image Icon
        {
            get { return _button.Image; }
            set { _button.Image = value; }
        }

        public DialogButton Click()
        {
            _button.PerformClick();
            return this;
        }

        public DialogButton Click(EventHandler clickAction)
        {
            _button.Click += clickAction;
            return this;
        }

        public static DialogButton FromButton(Button button)
        {
            return new DialogButton(button);
        }

        public static implicit operator Button(DialogButton button)
        {
            return button._button;
        }

        public static implicit operator DialogButton(Button button)
        {
            return new DialogButton(button);
        }
    }

    public class DialogButtonValues
    {
        public bool Enabled { get; set; }
        public EventHandler Click { get; set; }
        public Image Icon { get; set; }
        public string Text { get; set; }

        public DialogButtonValues()
        {
            Enabled = true;
            Text = "Button";
        }
    }

    [Flags]
    public enum DialogCreationOptions : int
    {
        None = 0,
        AutoOpen = 1,
        Draggable = 2,
        Modal = 4,
        Resizable = 8,
        AlwaysOnTop = 16
    }
}
